using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Ltf.Remoting.RemoteEvents;
using Ltf.Remoting.Operations;
using Ltf.Remoting.TeamFoundation;
using Microsoft.TeamFoundation.VersionControl.Client;
using System.IO;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Ltf.Remoting.Server;
using Ltf.Remoting.TFAccess;
// just some comments for testing changes
namespace Ltf.MonitorLizard.Forms
{
	[FormType(FormTypes.BranchTarget)]

	public partial class BranchTarget : Form
	{

		private TFServerConnection connection;

		private Workspace workspace;

		

		public BranchTarget(string[] pathList, LizardEventArgs args)
		{
			InitializeComponent();
			connection = ServerConnections.GetConnectionForPath(pathList[0]);
			string path = pathList[0];
			workspace = connection.GetWorkspace(path);
			string sourceItem = workspace.GetServerItemForLocalItem(path);
			txtSourcePath.Text = sourceItem;
			string targetPath = Path.GetDirectoryName(sourceItem).Replace('\\', '/');
			string itemName = Path.GetFileNameWithoutExtension(sourceItem);
			string extension = Path.GetExtension(sourceItem);
			string targetName = targetPath + "/" + itemName + "-branch" + extension;
			int i = 0;
			while (workspace.VersionControlServer.GetItems(targetName).Items.Length != 0)
			{
				targetName = targetPath + "/" + itemName + "-branch" + (++i).ToString() + extension;
			}
			txtTargetPath.Text = targetName;
			try
			{
				if (workspace.GetLocalItemForServerItem(targetPath) != string.Empty)
				{
					workingFolderPath = workspace.GetLocalItemForServerItem(targetPath);
					txtWorkingFolder.Enabled = false;
					btnWorkingFolderPicker.Enabled = false;
				}
			}
			catch
			{
				workingFolderPath = string.Empty;
				txtWorkingFolder.Enabled = true;
				btnWorkingFolderPicker.Enabled = true;
			}
			txtWorkingFolder.Text = workingFolderPath;
		}
		private void btnWorkingFolderPicker_Click(object sender, EventArgs e)
		{
			FolderBrowserDialog fbd = new FolderBrowserDialog();
			fbd.ShowNewFolderButton = true;
			DialogResult dr = fbd.ShowDialog();
			if (dr == DialogResult.OK)
			{
				workingFolderPath = fbd.SelectedPath;
				txtWorkingFolder.Text = workingFolderPath;
			}
		}


		private string workingFolderPath;

		private void btnSourcePicker_Click(object sender, EventArgs e)
		{
			TFProjectBrowser tfPB = new TFProjectBrowser(txtSourcePath.Text, workspace);
			tfPB.Text = "LizardTF Branch Source";
			DialogResult dr = tfPB.ShowDialog();
			if (dr == DialogResult.OK)
			{
				txtSourcePath.Text = tfPB.ProjectPath;
				if (tfPB.ProjectVersion != 0)
					txtSourcePath.Text = LizardFileAccess.SetPathVersion(txtSourcePath.Text, tfPB.ProjectVersion);
			}
		}

		private void btnTargetPicker_Click(object sender, EventArgs e)
		{
			string targetPath = string.Empty; // Path.GetDirectoryName(txtTargetPath.Text).Replace('\\', '/');
			string targetName = string.Empty; // Path.GetFileName(txtTargetPath.Text);
			try
			{
				targetPath = Path.GetDirectoryName(txtTargetPath.Text).Replace('\\', '/');
			}
			catch { }
			try
			{
				targetName = Path.GetFileName(txtTargetPath.Text);
			}
			catch { }
			TFProjectBrowser tfPB = new TFProjectBrowser(targetPath, true, workspace);
			DialogResult dr = tfPB.ShowDialog();
			if (dr == DialogResult.OK)
			{
				string targetserverPath = tfPB.ProjectPath;
				int v = 0;
				int d = 0;
				Ltf.Remoting.TFAccess.LizardFileAccess.GetNameAndVersionFromPath(targetserverPath, out targetPath, out v, out d);
				txtTargetPath.Text = targetPath + "/" + targetName;
				try
				{
					if (workspace.GetLocalItemForServerItem(targetPath) != string.Empty)
					{
						workingFolderPath = workspace.GetLocalItemForServerItem(targetPath);
						txtWorkingFolder.Enabled = false;
						btnWorkingFolderPicker.Enabled = false;
					}
				}
				catch
				{
					workingFolderPath = string.Empty;
					txtWorkingFolder.Enabled = ckbGetWorkingCopy.Checked;
					btnWorkingFolderPicker.Enabled = ckbGetWorkingCopy.Checked;
				}
			}
			txtWorkingFolder.Text = workingFolderPath;
		}

		private void btnCancel_Click(object sender, EventArgs e)
		{
			this.Close();
		}

		private void btnOkay_Click(object sender, EventArgs e)
		{
			string targetPath = Path.GetDirectoryName(txtTargetPath.Text).Replace('\\', '/');
			string wf = null;
			if (workingFolderPath != string.Empty)
				workspace.TryGetServerItemForLocalItem(workingFolderPath);
			string localTarget = workspace.TryGetLocalItemForServerItem(targetPath);
			int[] workItems = new int[0];
			if (chkCheckInImmediately.Checked && !ValidateChackInArgs(out workItems))
				return;

			if (ckbGetWorkingCopy.Checked)
			{
				if (wf != null && wf != targetPath)
				{
					MessageBox.Show(string.Format("The selected working copy path already has a server repository item mapped to it ('{0}'). You must select an unmapped path for the working copy of the branch", workingFolderPath),
						"Path Already Mapped", MessageBoxButtons.OK, MessageBoxIcon.Error);
					return;
				}
				else if (wf == null && Directory.Exists(txtWorkingFolder.Text))
				{
					workspace.CreateMapping(new WorkingFolder(targetPath, txtWorkingFolder.Text));
				}
				else if (!Directory.Exists(txtWorkingFolder.Text))
				{
					DialogResult dr = MessageBox.Show("The selected working copy path does not exist. Would you like to create it.",
						"Path Does Not Exist", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
					if (dr == DialogResult.Cancel)
						return;
					try
					{
						Directory.CreateDirectory(txtWorkingFolder.Text);
					}
					catch (Exception ex)
					{
						MessageBox.Show(string.Format("Creation of the working folder failed with the following message:\r\n{0}", ex.Message),
							"Create Path Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
						return;
					}
				}
			}
			else
			{
				if (localTarget == null)
				{
					MessageBox.Show("The selected target path does not have a local mapping. You must use 'Get local working copy..' option if the target path does not have an existing mapping.",
						"Path Does Not Exist", MessageBoxButtons.OK, MessageBoxIcon.Error);
					return;
				}
			}
			WorkspaceOperators wso = null;
			try
			{
				wso = new WorkspaceOperators(connection, workspace);
				wso.Branch(txtSourcePath.Text, txtTargetPath.Text, ckbGetWorkingCopy.Checked);
				if (ckbGetWorkingCopy.Checked)
				{
					ServerFunctions sf = new ServerFunctions();
					sf.StatusScan(workspace.GetLocalItemForServerItem(txtTargetPath.Text));
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show(string.Format("Branch operation of '{0}' to '{1}' failed with the message:\r\n {2}", txtSourcePath, txtTargetPath, ex.Message),
					"Branch Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
				return;
			}



			if (chkCheckInImmediately.Checked)
			{
				CheckInBranch(wso, workItems);
			}
			this.Close();
		}

		private void ckbGetWorkingCopy_CheckedChanged(object sender, EventArgs e)
		{
			txtWorkingFolder.Text = ckbGetWorkingCopy.Checked ? txtWorkingFolder.Text : string.Empty;
			txtWorkingFolder.Enabled = ckbGetWorkingCopy.Checked;
			btnWorkingFolderPicker.Enabled = ckbGetWorkingCopy.Checked;

		}

		private void chkCheckInImmediately_CheckedChanged(object sender, EventArgs e)
		{
			if (chkCheckInImmediately.Checked)
			{
				grbComments.Visible = true;
				this.MaximumSize = new Size(this.MaximumSize.Width, 347);
				this.Height = 347;
				this.MinimumSize = new Size(this.MinimumSize.Width, 347);
				if (txtComments.Text == string.Empty)
					txtComments.Text = "New branch taken from " + txtSourcePath.Text;
			}
			else
			{
				grbComments.Visible = false;
				this.MinimumSize = new Size(this.MinimumSize.Width, 217);
				this.Height = 217;
				this.MaximumSize = new Size(this.MaximumSize.Width, 217);
			}
		}

		private bool ValidateChackInArgs(out int[] workItems)
		{
			workItems = new int[0];
			if (txtComments.Text == string.Empty)
			{
				MessageBox.Show("Please supply a comment for this check-in.", "No Check-In comments.");
				return false;
			}

			try
			{
				workItems = GetSelectedWorkItems();
			}
			catch (ArgumentException argEx)
			{
				MessageBox.Show(argEx.Message, "Invalid WorkItems");
				return false;
			}

			return true;
		}

		private void CheckInBranch(WorkspaceOperators wso, int[] workItems)
		{

			using (new HourGlass(this))
			{
				PendingChange[] changes = wso.GetPendingChanges(txtTargetPath.Text, RecursionType.Full);

				try
				{
					int cs = wso.CheckIn(changes, txtComments.Text, workItems, ckbResolveWorkItems.Checked);
					if (cs > 0)
						MessageBox.Show("Check-in operation completed and created changeset :" + cs.ToString(), "Check-In Complete");
					else
						MessageBox.Show("Check-in operation completed, no files changed and no changeset created.", "Check-In Complete");
				}
				catch (Exception ex)
				{
					MessageBox.Show("Check-in operation failed with the message :" + ex.Message, "Check-In Failed");
					return;
				}

			}
		}

		public int[] GetSelectedWorkItems()
		{
			if (txtWorkItems.Text.Trim() == string.Empty)
				return new int[] { };
			WorkItemStore workItemStore = new WorkItemStore(connection.TeamFoundationServer);
			string[] itemNumbers = txtWorkItems.Text.Split(',');
			List<int> validItemIds = new List<int>();
			List<string> invalidItemNumbers = new List<string>();
			foreach (string itemNumber in itemNumbers)
			{
				int itemId;
				if (int.TryParse(itemNumber, out itemId))
				{
					try
					{
						workItemStore.GetWorkItem(itemId);
						validItemIds.Add(itemId);
					}
					catch (Exception ex)
					{
						invalidItemNumbers.Add(itemNumber);
					}

				}
				else
				{
					invalidItemNumbers.Add(itemNumber);
				}
			}
			if (invalidItemNumbers.Count == 0)
				return validItemIds.ToArray();

			throw new ArgumentException(string.Format("The following are not valid workitem ids : {0}", string.Join(", ", invalidItemNumbers.ToArray())));

		}

		private void txtTargetPath_TextChanged(object sender, EventArgs e)
		{
			try
			{
				string targetPath = Path.GetDirectoryName(txtTargetPath.Text).Replace('\\', '/');
				if (workspace.GetLocalItemForServerItem(targetPath) != string.Empty)
				{
					workingFolderPath = workspace.GetLocalItemForServerItem(targetPath);
					txtWorkingFolder.Enabled = false;
					btnWorkingFolderPicker.Enabled = false;
				}
			}
			catch
			{
				workingFolderPath = string.Empty;
				txtWorkingFolder.Enabled = true;
				btnWorkingFolderPicker.Enabled = true;
			}
			txtWorkingFolder.Text = workingFolderPath;
		}

	}
}